from abc import abstractmethod
import tkinter as tk
from tkinter import font
from tkinter import ttk

from SelectCardFrame import SelectCardFrame
from ImageCanvas import ImageCanvas


class tkToolGUI:
    __slots__ = (
        "root",
        "detect_canvas",
        "data_canvas",
        "cards_frame",
        "camera_btn",
        "save_btn",
        "file_btn",
        "delete_btn",
        "setting_save_btn",
        "setting_load_btn",
        "data_select",
        "camera_label",
        "detect_label",
        "path_label",
    )

    def __init__(self, root):
        # 设置窗口
        self.root = root
        self.root.title("Hand Data Collection tkTool")
        self.root.geometry(str(1200) + "x" + str(470))
        self.root.minsize(1000, 370)

        label_font = font.Font(family="微软雅黑", size=12)
        self.root.option_add("*Font", label_font)

        style = ttk.Style()
        style.configure("TButton", font=("微软雅黑", 12))

        self.init_widgets()
        self.init_layout()

    def init_widgets(self):
        """创建控件"""
        self.detect_canvas = ImageCanvas(self.root)
        self.data_canvas = ImageCanvas(self.root)
        self.cards_frame = SelectCardFrame(self.root)
        self.camera_btn = ttk.Button(
            self.root, text="开启手部关键点检测(w)", command=self.camera_btn_callback
        )
        self.save_btn = ttk.Button(
            self.root, text="保存手部数据(a)", command=self.save_btn_callback
        )
        self.file_btn = ttk.Button(
            self.root, text="设置数据文件路径(f)", command=self.file_btn_callback
        )
        self.setting_save_btn = ttk.Button(
            self.root, text="保存当前设置", command=self.setting_save_btn_callback
        )
        self.delete_btn = ttk.Button(
            self.root, text="删除数据(d)", command=self.delete_btn_callback
        )
        self.setting_load_btn = ttk.Button(
            self.root, text="加载我的设置", command=self.setting_load_btn_callback
        )
        # 判断输入的是否为正整数
        vcmd = (self.root.register(lambda P: str.isdigit(P)), "%P")
        self.data_select = ttk.Spinbox(
            self.root,
            justify="center",
            from_=0,
            to=100_000_000_000_000,
            increment=1,  # 箭头步长
            validate="key",  # 在键盘输入的情况下进行验证
            validatecommand=vcmd,  # 验证函数
            command=self.data_select_callback,
        )  # 绑定 <Return> 和 <FocusOut> 事件到回调函数
        self.data_select.bind("<Return>", self.data_select_callback)
        self.data_select.bind("<FocusOut>", self.data_select_callback)
        self.data_select.set(0)  # 设定初始值,未加载数据文件时默认为0
        self.camera_label = ttk.Label(self.root, text="未开启摄像头", anchor="center")
        self.detect_label = ttk.Label(
            self.root, text="未开始检测手部数据", anchor="center"
        )
        self.path_label = ttk.Label(self.root, text="没有选择文件", anchor="w")

    def init_layout(self):
        """初始化布局"""
        # 设置布局比重
        self.root.grid_rowconfigure(0, weight=10)
        self.root.grid_rowconfigure(1, weight=1)
        self.root.grid_rowconfigure(2, weight=1)
        self.root.grid_rowconfigure(3, weight=1)
        self.root.grid_columnconfigure(0, weight=20)
        self.root.grid_columnconfigure(1, weight=20)
        self.root.grid_columnconfigure(2, weight=20)
        self.root.grid_columnconfigure(3, weight=20)
        self.root.grid_columnconfigure(4, weight=1)
        self.root.grid_columnconfigure(5, weight=1)

        # 设置控件布局
        self.detect_canvas.grid(
            row=0, column=0, columnspan=2, padx=5, pady=5, sticky="nsew"
        )
        self.data_canvas.grid(
            row=0, column=2, columnspan=2, padx=5, pady=5, sticky="nsew"
        )
        self.camera_btn.grid(
            row=1, column=0, columnspan=2, padx=5, pady=5, sticky="nsew"
        )
        self.save_btn.grid(row=1, column=2, columnspan=2, padx=5, pady=5, sticky="nsew")
        self.file_btn.grid(row=3, column=0, padx=5, pady=5, sticky="nsew")
        self.setting_save_btn.grid(row=3, column=4, padx=5, pady=5, sticky="nsew")
        self.setting_load_btn.grid(row=3, column=5, padx=5, pady=5, sticky="nsew")
        self.delete_btn.grid(row=2, column=2, padx=5, pady=5, sticky="nsew")
        self.data_select.grid(row=2, column=3, padx=5, pady=5, sticky="nsew")
        self.cards_frame.grid(
            row=0, column=4, rowspan=3, columnspan=2, padx=5, pady=5, sticky="nsew"
        )
        self.camera_label.grid(row=2, column=0, padx=5, pady=5, sticky="nsew")
        self.detect_label.grid(row=2, column=1, padx=5, pady=5, sticky="nsew")
        self.path_label.grid(
            row=3, column=1, columnspan=3, padx=5, rowspan=2, sticky="nsew"
        )

    @abstractmethod
    def run(self):
        """事件处理和循环"""
        self.root.mainloop()  # 运行主循环

    @abstractmethod
    def camera_btn_callback(self):
        pass

    @abstractmethod
    def save_btn_callback(self):
        pass

    @abstractmethod
    def file_btn_callback(self):
        pass

    @abstractmethod
    def setting_save_btn_callback(self):
        pass

    @abstractmethod
    def setting_load_btn_callback(self):
        pass

    @abstractmethod
    def delete_btn_callback(self):
        pass

    @abstractmethod
    def data_select_callback(self, event=None):
        pass


if __name__ == "__main__":
    root = tk.Tk()
    app = tkToolGUI(root)
    app.run()
